﻿/*
 *       This file is part of VFC.
 *
 *        VFC is free software: you can redistribute it and/or modify
 *        it under the terms of the GNU General Public License as published by
 *        the Free Software Foundation, either version 3 of the License, or
 *        (at your option) any later version.
 *
 *        VFC is distributed in the hope that it will be useful,
 *        but WITHOUT ANY WARRANTY; without even the implied warranty of
 *        MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 *        GNU General Public License for more details.
 *
 *        You should have received a copy of the GNU General Public License
 *        along with VFC.  If not, see <http://www.gnu.org/licenses/>.
 */


using System;
using System.Collections.Generic;
//using System.Linq;
using System.Text;
using System.Windows.Forms;
using SlimDX;
using SlimDX.Direct3D9;

namespace VFC.Emu
{
    class SDX
    {
        Direct3D d3d = new Direct3D();
        public Device Dx9Device;
        PresentParameters pp = new PresentParameters();
        VertexElement[] vElem;
        SlimDX.Direct3D9.Font fnt;
        Control _control;

        public SDX(Control control)
        {
            _control = control;
            pp.EnableAutoDepthStencil = true;
            pp.AutoDepthStencilFormat = Format.D16;
            pp.BackBufferWidth = control.Width;
            pp.BackBufferHeight = control.Height;
            pp.BackBufferCount = 1;
            pp.SwapEffect = SwapEffect.Discard;
            pp.Windowed = true;
            pp.PresentationInterval = PresentInterval.Default;
        }

        public void Init()
        {
            if (VFC.Config.Video.Mode == 1)
            {
                //Hardware Mode
                Dx9Device = new Device(d3d, 0, DeviceType.Hardware, _control.Handle, CreateFlags.HardwareVertexProcessing, pp);
            }
            else
            {
                //Hardware Mode
                Dx9Device = new Device(d3d, 0, DeviceType.Hardware, _control.Handle, CreateFlags.SoftwareVertexProcessing, pp);
            }

            //Vertex Declaration.....
            vElem = new VertexElement[] {
                new VertexElement(0, 0, DeclarationType.Float4, DeclarationMethod.Default, DeclarationUsage.PositionTransformed, 0),
        		new VertexElement(0, 16, DeclarationType.Color, DeclarationMethod.Default, DeclarationUsage.Color, 0),
				VertexElement.VertexDeclarationEnd
            };
            Dx9Device.VertexDeclaration = new VertexDeclaration(Dx9Device, vElem);
        }

        public void SetInternalResolution(int width, int height)
        {
            pp.BackBufferWidth = width;
            pp.BackBufferHeight = height;
        }

        public void FullScreen()
        {
            pp.Windowed = false;
        }

        public void Windowed()
        {
            pp.Windowed = true;
        }

        public void SetFont(System.Drawing.Font font)
        {
            fnt = new Font(Dx9Device, font);
        }

        public void Draw(VertexBuffer vb)
        {
            Dx9Device.BeginScene();
            Dx9Device.SetStreamSource(0, vb, 0, 20);
            Dx9Device.DrawPrimitives(PrimitiveType.TriangleList, 0, 1);
            Dx9Device.EndScene();
        }

        public void Draw(Plane.Square square)
        {
            Dx9Device.BeginScene();
            Dx9Device.SetStreamSource(0, square.GetVertexBuffer(), 0, 20);
            Dx9Device.DrawPrimitives(PrimitiveType.TriangleStrip, 0, 2);
            Dx9Device.EndScene();
        }

        public void Draw(int x, int y, String txt, System.Drawing.Color color)
        {
            Dx9Device.BeginScene();
            fnt.DrawString(null, txt, x, y, color);
            Dx9Device.EndScene();
        }

        public void Clear(System.Drawing.Color color)
        {
            Dx9Device.Clear(ClearFlags.Target | ClearFlags.ZBuffer, color, 1.0f, 0);
        }

        public void Present()
        {
            Dx9Device.Present(); 
        }

        ~SDX()
        {
            d3d.Dispose();
            Dx9Device.Dispose(); 
        }
    }

    namespace Plane
    {
        struct Vertex
        {
            public Vector4 pos;
            public int color;
        }

        class Square
        {
            VertexBuffer v;
            Vertex[] vt = new Vertex[4];
            
            public Square(Device device, System.Drawing.Color _Color, float X, float Y, float Width, float Height)
            {
                v = new VertexBuffer(device, 4 * 20, Usage.WriteOnly, VertexFormat.None, Pool.Managed);
                
                //VS2005 Compatibility....
                vt[0].color = _Color.ToArgb();
                vt[1].color = _Color.ToArgb();
                vt[2].color = _Color.ToArgb();
                vt[3].color = _Color.ToArgb();

                vt[0].pos = new Vector4(X, Y + Height, 0, 0);
                vt[1].pos = new Vector4(X, Y, 0, 0);
                vt[2].pos = new Vector4(X + Width, Y + Height, 0, 0);
                vt[3].pos = new Vector4(X + Width, Y, 0, 0);

                //v.Lock(0, 0, LockFlags.None).WriteRange(new Vertex[] {
                    //new Vertex() { color = _Color.ToArgb(), pos = new Vector4(X, Y + Height, 0, 0) },
                    //new Vertex() { color = _Color.ToArgb(), pos = new Vector4(X, Y, 0, 0) },
                    //new Vertex() { color = _Color.ToArgb(), pos = new Vector4(X + Width, Y + Height, 0, 0) },
                    //new Vertex() { color = _Color.ToArgb(), pos = new Vector4(X + Width, Y, 0, 0) }
                //});

                v.Lock(0, 0, LockFlags.None).WriteRange(vt);
                v.Unlock();
            }

            public VertexBuffer GetVertexBuffer()
            {
                return v;
            }

            public void Dispose()
            {
                v.Dispose();
            }
        }
    }
}
